home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows Undocumented File Formats
/
Windows Undocumented File Formats.img
/
CHAP10
/
LEDUMP.C
next >
Wrap
C/C++ Source or Header
|
1997-07-20
|
8KB
|
320 lines
/**********************************************************************
*
* PROGRAM: LEDUMP.C
*
* PURPOSE: Dump 'LE' file info
*
* Copyright 1997, Mike Wallace and Pete Davis
*
* Chapter 10, LE File Format, from Undocumented Windows File Formats,
* published by R&D Books, an imprint of Miller Freeman, Inc.
*
**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <windows.h>
#include "ledump.h"
/* Make this big thing global since we'll need it everywhere. */
LEHEADER LEHeader;
long LEStart; /* Keep track of start of LE Header */
BOOL SkipMZ(FILE *LEFile)
{
MZHEADER MZHeader;
fread(&MZHeader, sizeof(MZHeader), 1, LEFile);
if (MZHeader.MZMagic[0] != 'M' || MZHeader.MZMagic[1] != 'Z')
{
printf("This is not an executable file!\n");
return FALSE;
}
if (!MZHeader.LEOff)
{
printf("This is a DOS executable.\n");
return FALSE;
}
fseek(LEFile, MZHeader.LEOff, SEEK_SET);
return TRUE;
}
void DumpHeaderInfo()
{
DWORD Flags;
Flags = LEHeader.ModuleFlags; /* Get it into an easier to type variable */
printf("CPU Required: ");
switch(LEHeader.CPUType)
{
case CPU_286:
printf("80286\n");
break;
case CPU_386:
printf("80386\n");
break;
case CPU_486:
printf("80486\n");
break;
}
printf("OS Required: ");
switch(LEHeader.OSType)
{
case OS_UNKNOWN:
printf("Unknown\n");
break;
case OS_OS2:
printf("OS/2\n");
break;
case OS_WINDOWS:
printf("Windows\n");
break;
case OS_DOS4X:
printf("DOS 4.x\n");
break;
case OS_WINDOWS386:
printf("Windows 386 Enhanced Mode\n");
break;
}
printf("Initial EIP: %lX:%08lX\n", LEHeader.EIPObjNum, LEHeader.EIP);
printf("Initial ESP: %lX:%08lX\n", LEHeader.ESPObjNum, LEHeader.ESP);
printf("Flags: 0x%08lX\n", Flags);
if (Flags & MOD_PERPROCESSLIBINIT)
printf("- Per Process Library Initialization\n");
if (Flags & MOD_INTERNALFIXUPS)
printf("- Internal Fixups\n");
if (Flags & MOD_EXTERNALFIXUPS)
printf("- External Fixups\n");
if ( (Flags & MOD_USES_PM) == MOD_USES_PM)
printf("- Uses Presentation Manager\n");
else
{
if (Flags & MOD_INCOMPAT_PM)
printf("- Incompatible with Presentation Manager\n");
if (Flags & MOD_COMPAT_PM)
printf("- Compatible with Presentation Manager\n");
}
if (Flags & MOD_NOTLOADABLE)
printf("- Module is not loadable.\n");
if ( (Flags & MOD_PROTLIBMOD) == MOD_PROTLIBMOD)
printf("- Protected Memory Library Module\n");
else if ( (Flags & MOD_VIRTDEVICEDRVR) == MOD_VIRTDEVICEDRVR)
printf("- Virtual Device Driver Module\n");
else
{
if (Flags & MOD_LIBMOD)
printf("- Library Module\n");
if (Flags & MOD_PHYSDEVICEDRVR)
printf("- Physical Device Driver\n");
}
if (Flags & MOD_PERPROCLIBTERM)
printf("- Per-Process Library Termination\n");
printf("\n");
}
void DumpObjectTable(FILE *LEFile)
{
DWORD i;
OBJTBLENTRY ote;
printf("There are %ld objects in the Object Table.\n", LEHeader.NumObjects);
fseek(LEFile, LEStart + LEHeader.ObjTblOffset, SEEK_SET);
for (i=1; i<=LEHeader.NumObjects; i++)
{
fread(&ote, sizeof(ote), 1, LEFile);
printf("Segment #: %ld Size: 0x%08lX Reloc Addr: 0x%08lX # Pages: %ld\n",
i, ote.VirtualSize, ote.RelocBaseAddr, ote.NumPgTblEntries);
if (i == LEHeader.AutoDSObj)
printf("Auto Data Segment\n");
printf("Flags:\n");
if (ote.ObjectFlags & OBJ_READABLE)
printf("Readable\n");
if (ote.ObjectFlags & OBJ_WRITEABLE)
printf("Writeable\n");
if (ote.ObjectFlags & OBJ_EXECUTABLE)
printf("Executable\n");
if (ote.ObjectFlags & OBJ_RESOURCE)
printf("Resource\n");
if (ote.ObjectFlags & OBJ_DISCARDABLE)
printf("Discardable\n");
if (ote.ObjectFlags & OBJ_SHARED)
printf("Shared\n");
if (ote.ObjectFlags & OBJ_PRELOAD)
printf("Preload\n");
if (ote.ObjectFlags & OBJ_INVALID)
printf("Invalid\n");
if ( (ote.ObjectFlags & OBJ_RESIDENTCONTIG) == OBJ_RESIDENTCONTIG)
printf("Resident & Contiguous\n");
else
{
if (ote.ObjectFlags & OBJ_ZEROFILLED)
printf("Zero-Filled\n");
if (ote.ObjectFlags & OBJ_RESIDENT)
printf("Resident\n");
}
if (ote.ObjectFlags & OBJ_RESERVED)
printf("Reserved\n");
if (ote.ObjectFlags & OBJ_1616ALIAS)
printf("16:16 Alias Required\n");
if (ote.ObjectFlags & OBJ_BIGDEFAULT)
printf("'Big' bit for segment descriptor\n");
if (ote.ObjectFlags & OBJ_CONFORM)
printf("Object is conforming to code\n");
if (ote.ObjectFlags & OBJ_PRIVILEGE)
printf("Object I/O privilege level\n");
printf("\n");
}
}
void DumpNameTable(FILE *LEFile, DWORD size)
{
DWORD Curr;
BYTE len;
char Name[257];
WORD Ord;
Curr = 0;
while (Curr < size)
{
fread(&len, sizeof(len), 1, LEFile);
Curr += (len + sizeof(len) + sizeof(Ord));
fread(Name, len, 1, LEFile);
Name[len] = 0x00;
fread(&Ord, sizeof(Ord), 1, LEFile);
printf("%u %s\n", Ord, Name);
}
}
/* Dumps the Resident and Non-Resident Name Tables */
void DumpNameTables(FILE *LEFile)
{
printf("\nResident Name Table\n");
printf("Ordinal Name\n");
fseek(LEFile, LEStart + LEHeader.ResNameTable, SEEK_SET);
DumpNameTable(LEFile, (LEHeader.EntryTable - LEHeader.ResNameTable) - 1);
printf("\n");
printf("Non-Resident Name Table\n");
printf("Ordinal Name\n");
fseek(LEFile, LEHeader.NonResTable, SEEK_SET);
DumpNameTable(LEFile, LEHeader.NonResSize - 1);
}
/*
void DumpImports(FILE *LEFile)
{
FIXUPREC FixupRec;
PROCBYNAME ProcByName;
PROCBYORD ProcByOrd;
long CurrLoc;
fseek(LEFile, LEStart+LEHeader.FixupRecTable, SEEK_SET);
}
*/
void Check4HeaderSurprises()
{
if (LEHeader.ByteOrder != ORD_LITTLEENDIAN)
printf("Byte Order is not Little Endian!\n");
if (LEHeader.WordOrder != ORD_LITTLEENDIAN)
printf("Word Order is not Little Endian!\n");
if (LEHeader.CPUType < CPU_386)
printf("Doesn't require a 386 or better!\n");
if (LEHeader.OSType != OS_WINDOWS386)
printf("Not a Windows386 VxD!\n");
if (LEHeader.ResourceTbl)
printf("Resource Table Found!\n");
if (LEHeader.NumResources)
printf("Num Resources Found!\n");
if (LEHeader.ModDirectTable)
printf("Module Directive Table Found!\n");
if (LEHeader.NumModDirect)
printf("NumModDirect Found!\n");
if (LEHeader.NumInstPreload)
printf("Instance Preloads Found!\n");
if (LEHeader.NumInstDemand)
printf("Instance Demands Found!\n");
if (LEHeader.FixupChecksum)
printf("Fixup Checksum Found!\n");
if (LEHeader.LoaderChecksum)
printf("Loader Checksum Found!\n");
if (LEHeader.PerPageChecksum)
printf("Per-Page Checksum Found!\n");
if (LEHeader.NonResChecksum)
printf("Non-Resident Name Table Checksum Found!\n");
}
void DumpLEFile(FILE *LEFile)
{
LEStart = ftell(LEFile);
fread(&LEHeader, sizeof(LEHeader), 1, LEFile);
if (LEHeader.LEMagic[0] != 'L' || LEHeader.LEMagic[1] != 'E')
{
printf("This is not an 'LE' executable.\n\n");
return;
}
DumpHeaderInfo();
Check4HeaderSurprises();
DumpObjectTable(LEFile);
DumpNameTables(LEFile);
// if (LEHeader.NumImports)
// DumpImports(LEFile);
}
void Usage(void)
{
printf("Usage: LEDump filename[.386]\n\n");
}
int main(int argc, char *argv[])
{
char filename[256];
FILE *LEFile;
if (argc < 2) {
Usage();
return EXIT_FAILURE;
}
strcpy(filename, argv[1]);
if (!strchr(filename, '.'))
strcat(filename, ".386");
if ((LEFile = fopen(filename, "rb")) == NULL) {
printf("%s does not exist!\n", filename);
return EXIT_FAILURE;
}
if (SkipMZ(LEFile))
{
printf("Dumping %s\n", filename);
DumpLEFile(LEFile);
}
fclose(LEFile);
return EXIT_SUCCESS;
}